package com.rambler.common.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.rambler.common.entity.GlobalConst;
import com.rambler.common.entity.TokenVerifyResult;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author rambler
 * @since 2021-03-31 21:15
 */
public class JWTUtil {
    public final static String SIGN = "1@2#4$%65^$#@";

    public static String getToken(Map<String, String> payload, Integer expireHours) {
        JWTCreator.Builder builder = JWT.create();
        /* 设置token过期时间 */
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.HOUR, expireHours);
        builder.withExpiresAt(calendar.getTime());
        /* 负载数据,claim可以理解成数据的key */
        payload.forEach(builder::withClaim);
        return builder.sign(Algorithm.HMAC256(SIGN));
    }

    /**
     * 验证token
     *
     * @param token token
     * @return 自定义TokenVerifyResult对象
     */
    public static TokenVerifyResult verify(String token) {
        TokenVerifyResult result = new TokenVerifyResult();
        try {
            DecodedJWT verify = JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token);

            result.setCode(200);

            // 提取载荷
            Map<String, String> payload = new HashMap<>();
            Map<String, Claim> stringClaimHashMap = verify.getClaims();
            stringClaimHashMap.forEach((key, value) -> {
                payload.put(key, value.asString()); // 用 asString() 比 toString() 更干净
            });
            result.setData(payload);

            // 计算剩余有效时间（秒）
            Date expiresAt = verify.getExpiresAt();
            if (expiresAt != null) {
                long now = System.currentTimeMillis();
                long diffMillis = expiresAt.getTime() - now;
                // 避免负数
                long diffSeconds = Math.max(diffMillis / 1000, 0);
                result.setExpiresTime(diffSeconds);
            }

            return result;
        } catch (SignatureVerificationException e) {
            result.setCode(GlobalConst.UN_LOGIN);
            result.setMessage("无效签名");
        } catch (TokenExpiredException e) {
            result.setCode(GlobalConst.UN_LOGIN);
            result.setMessage("token已过期");
            result.setExpiresTime(0L);
        } catch (AlgorithmMismatchException e) {
            result.setCode(GlobalConst.UN_LOGIN);
            result.setMessage("token签名算法不一致");
        } catch (Exception e) {
            result.setCode(GlobalConst.UN_LOGIN);
            result.setMessage("token无效");
        }
        return result;
    }


    public static String tokenParse(String token, String key) {
        // 在此签名获取JWT
        DecodedJWT verify = JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token);
        Claim claim = verify.getClaim(key);
        if (claim != null) {
            return claim.asString();
        } else {
            return null;
        }
    }
}
